package com.tang.sharding.core;

import com.alibaba.druid.pool.DruidDataSource;
import com.tang.sharding.ShardProperties;
import com.tang.sharding.schedule.config.DefaultScheduleConfigurer;
import com.tang.sharding.schedule.task.jdbc.JdbcManager;
import com.tang.sharding.schedule.task.manager.CronTaskManager;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;

/**
 * @author Tang
 * @classname ShardJdbcConfig
 * @description [ 初始版本，只能有一个数据源 ]
 * @date 2021/7/30 9:20
 */
@ConditionalOnProperty(prefix = "sharding", name = "enable", havingValue = "true", matchIfMissing = false)
@EnableConfigurationProperties(value = {ShardProperties.class})
@Configuration
public class ShardJdbcConfig implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    private Properties properties;

    @Resource
    private ShardProperties shardProperties;

    public ShardJdbcConfig() {
        this(null);
    }

    public ShardJdbcConfig(Properties properties) {
        this.properties = properties;
        this.properties = Optional
                .ofNullable(this.properties)
                .orElse(new Properties());
        this.properties.put("sql.show", true);
        this.properties.put("sql.simple", true);
    }

    @Bean
    @Primary
    public DataSource dataSource() throws Exception {
        ScheduledTaskRegistrar scheduledTaskRegistrar = DefaultScheduleConfigurer.getScheduledTaskRegistrar();
        ShardDataSourceFactory shardDataSourceFactory = new ShardDataSourceFactory(this.shardProperties);
        Map<String, DataSource> dataSourceMap = buildDataSource();
        shardDataSourceFactory.setTaskManager(new CronTaskManager(scheduledTaskRegistrar));
        shardDataSourceFactory.setJdbcManager(new JdbcManager(dataSourceMap.get(this.shardProperties.getDataSourceName())));
        return shardDataSourceFactory.createDataSource(this.properties, dataSourceMap);
    }

    /**
     * 数据源配置
     */
    private Map<String, DataSource> buildDataSource() {
        Map<String, DataSource> dataSourceMap = new HashMap<>(10);
        this.applicationContext.getBeanProvider(DruidDataSource.class).ifUnique(druidDataSource -> {
            dataSourceMap.put(shardProperties.getDataSourceName(), druidDataSource);
        });
        if (CollectionUtils.isEmpty(dataSourceMap)) {
            throw new RuntimeException("缺少数据源配置...");
        }
        return dataSourceMap;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}